#include "Subsystems/BlockBehaviors/SubsystemFenceGateBlockBehavior.h"
#include "Subsystems/SubsystemTerrain.h"
#include "Managers/BlocksManager.h"
#include "Terrain/Terrain.h"

#include "Log.h"
#include "GameSingleton.h"
#include "Blocks/FenceGateBlock.h"
#include "Blocks/WoodenFenceGateBlock.h"

namespace PocketSurvival
{
    bool SubsystemFenceGateBlockBehavior::openCloseGate(int32_t x, int32_t y, int32_t z, bool open)
    {
        int32_t cellValue = m_terrain->getCellValue(x, y, z);
        int32_t cellContents = Terrain::ExtractContents(cellValue);
        if (GameSingleton::blocksManager->blocks[cellContents]->isBlock<FenceGateBlock*>())
        {
            int32_t data = FenceGateBlock::SetOpen(Terrain::ExtractData(cellValue), open);
            int32_t value = Terrain::ReplaceData(cellValue, data);
            m_terrain->changeCell(x, y, z, value);
            return true;
        }
        return false;
    }

    bool SubsystemFenceGateBlockBehavior::isGateElectricallyConnected(const Point3 &point)
    {
        int32_t cellvalue = m_terrain->getCellValue(point);
        int32_t cellContents = Terrain::ExtractContents(cellvalue);
        int32_t data = Terrain::ExtractData(cellvalue);
        if(GameSingleton::blocksManager->blocks[cellContents]->isBlock<FenceGateBlock*>())
        {
            return false;
        }
        return false;
    }

    bool SubsystemFenceGateBlockBehavior::onInteract(const TerrainRaycastResult &raycastResult, ComponentMiner *componentMiner)
    {
        const CellFace &cellFace = raycastResult.cellFace;
        int32_t cellValue = m_terrain->getCellValue(cellFace.point);
        int32_t num = Terrain::ExtractContents(cellValue);
        int32_t data = Terrain::ExtractData(cellValue);
        if(num == WoodenFenceGateBlock::Index() || false == isGateElectricallyConnected(cellFace.point))
        {
            bool open = FenceGateBlock::GetOpen(data);
            return openCloseGate(cellFace.point, !open);
        }
        return true;
    }

    void SubsystemFenceGateBlockBehavior::load(const nlohmann::json &json)
    {
        m_terrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();
    }

    static const std::string subsystemName = "FenceGateBlockBehavior";
    const std::string &SubsystemFenceGateBlockBehavior::getName() const
    {
        return subsystemName;
    }

} // namespace PocketSurvival
